package com.jike.task.week01;

import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.Method;

/**
 * @author Administrator
 */
public class HelloClassLoader extends ClassLoader {

    public static void main(String[] args) throws Exception {
        Class<?> hello = new HelloClassLoader().findClass("Hello");
        Method method = hello.getMethod("hello", null);
        method.invoke(hello.getDeclaredConstructor().newInstance(), null);
    }

    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        //读取hello.xlass文件
        File rootFile = new File("");
        String canonicalPath = null;
        try {
            canonicalPath = rootFile.getCanonicalPath();
        } catch (IOException e) {
            e.printStackTrace();
        }
        File xlassFile = new File(canonicalPath + "/src/main/resources/file/Hello.xlass");
        File classFile = new File(canonicalPath + "/src/main/resources/file/Hello.class");
        byte[] fileBytes = new byte[1024];
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream((int) xlassFile.length());
        BufferedInputStream bufferedInputStream = null;
        try {
            bufferedInputStream = new BufferedInputStream(new FileInputStream(xlassFile));
            int buf_size = 1024;
            byte[] buffer = new byte[buf_size];
            int len = 0;
            while (-1 != (len = bufferedInputStream.read(buffer, 0, buf_size))) {
                byteArrayOutputStream.write(buffer, 0, len);
            }
            fileBytes = byteArrayOutputStream.toByteArray();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (bufferedInputStream != null) {
                try {
                    bufferedInputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (byteArrayOutputStream != null) {
                try {
                    byteArrayOutputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        byte[] s = new byte[fileBytes.length];
        for (int i = 0; i < fileBytes.length; i++) {
            s[i] = (byte) (0xFF - fileBytes[i]);
        }
        try {
            FileOutputStream fos = new FileOutputStream(classFile);
            fos.write(s);
            fos.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return defineClass(name, s, 0, s.length);
    }
}
